from typing import List, Optional
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer
from sqlalchemy.orm import Session

from app.core.database.connection import get_database
from app.core.security.auth import auth_manager
from app.domains.user.services import UserService
from app.shared.constants.enums import UserRole
from app.shared.exceptions.base import AuthenticationException, AuthorizationException
from app.shared.constants.status_codes import BusinessCode
import logging

logger = logging.getLogger(__name__)

security = HTTPBearer()


async def get_current_user(
    token: str = Depends(security),
    db: Session = Depends(get_database)
) -> dict:
    """获取当前用户信息"""
    try:
        # 从Bearer token中提取令牌
        access_token = token.credentials
        
        # 解码令牌获取用户信息
        user_info = auth_manager.get_current_user_from_token(access_token)
        
        # 验证用户是否存在且激活
        user_service = UserService(db)
        user = user_service.get_user_by_id(user_info["user_id"])
        
        if not user.is_active:
            logger.warning(f"⚠️  用户已禁用: {user.username}")
            raise AuthenticationException("用户账号已被禁用")
        
        return user_info
        
    except AuthenticationException:
        raise
    except Exception as e:
        logger.warning(f"⚠️  用户认证失败: {e}")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="认证失败，请重新登录",
            headers={"WWW-Authenticate": "Bearer"},
        )


def require_roles(required_roles: List[UserRole]):
    """要求指定角色权限的依赖函数"""
    
    def role_checker(
        current_user: dict = Depends(get_current_user)
    ) -> dict:
        user_role = UserRole(current_user["role"])
        
        if user_role not in required_roles:
            logger.warning(
                f"⚠️  权限不足: 用户 {current_user['username']} "
                f"(角色: {user_role}) 尝试访问需要 {required_roles} 权限的资源"
            )
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="权限不足，无法访问此资源",
            )
        
        return current_user
    
    return role_checker


def require_admin(
    current_user: dict = Depends(get_current_user)
) -> dict:
    """要求管理员权限"""
    return require_roles([UserRole.ADMIN])(current_user)


def require_manager_or_admin(
    current_user: dict = Depends(get_current_user)  
) -> dict:
    """要求经理或管理员权限"""
    return require_roles([UserRole.MANAGER, UserRole.ADMIN])(current_user)


def require_technician_or_above(
    current_user: dict = Depends(get_current_user)
) -> dict:
    """要求技术员及以上权限"""
    return require_roles([UserRole.TECHNICIAN, UserRole.MANAGER, UserRole.ADMIN])(current_user)


async def get_current_user_optional(
    token: Optional[str] = Depends(security),
    db: Session = Depends(get_database)
) -> Optional[dict]:
    """获取当前用户信息（可选）"""
    if not token:
        return None
        
    try:
        return await get_current_user(token, db)
    except:
        return None


class ResourcePermission:
    """资源权限检查"""
    
    @staticmethod
    def can_manage_users(user_role: UserRole) -> bool:
        """是否可以管理用户"""
        return user_role in [UserRole.ADMIN]
    
    @staticmethod
    def can_view_users(user_role: UserRole) -> bool:
        """是否可以查看用户列表"""
        return user_role in [UserRole.ADMIN, UserRole.MANAGER]
    
    @staticmethod
    def can_manage_devices(user_role: UserRole) -> bool:
        """是否可以管理设备"""
        return user_role in [UserRole.ADMIN, UserRole.MANAGER]
    
    @staticmethod
    def can_control_devices(user_role: UserRole) -> bool:
        """是否可以控制设备"""
        return user_role in [UserRole.ADMIN, UserRole.MANAGER, UserRole.TECHNICIAN]
    
    @staticmethod
    def can_view_devices(user_role: UserRole) -> bool:
        """是否可以查看设备"""
        return True  # 所有用户都可以查看设备
    
    @staticmethod
    def can_create_work_orders(user_role: UserRole) -> bool:
        """是否可以创建工单"""
        return user_role in [UserRole.ADMIN, UserRole.MANAGER, UserRole.TECHNICIAN]
    
    @staticmethod
    def can_assign_work_orders(user_role: UserRole) -> bool:
        """是否可以分配工单"""
        return user_role in [UserRole.ADMIN, UserRole.MANAGER]
    
    @staticmethod
    def can_view_all_work_orders(user_role: UserRole) -> bool:
        """是否可以查看所有工单"""
        return user_role in [UserRole.ADMIN, UserRole.MANAGER]
    
    @staticmethod
    def can_manage_alerts(user_role: UserRole) -> bool:
        """是否可以管理告警"""
        return user_role in [UserRole.ADMIN, UserRole.MANAGER, UserRole.TECHNICIAN]
    
    @staticmethod
    def can_view_reports(user_role: UserRole) -> bool:
        """是否可以查看报表"""
        return user_role in [UserRole.ADMIN, UserRole.MANAGER]


def check_resource_permission(
    permission_check: callable,
    error_message: str = "权限不足"
):
    """检查资源权限的装饰器工厂"""
    
    def permission_checker(
        current_user: dict = Depends(get_current_user)
    ) -> dict:
        user_role = UserRole(current_user["role"])
        
        if not permission_check(user_role):
            logger.warning(
                f"⚠️  权限检查失败: 用户 {current_user['username']} "
                f"(角色: {user_role}) 没有权限执行此操作"
            )
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail=error_message,
            )
        
        return current_user
    
    return permission_checker